/**
 * @file wa_area.c
 * 
 */

/*********************
 *      INCLUDES
 *********************/
#include "wa_area.h"
 
/*********************
 *      DEFINES
 *********************/

/**********************
 *      TYPEDEFS
 **********************/

/**********************
 *  STATIC PROTOTYPES
 **********************/

/**********************
 *  STATIC VARIABLES
 **********************/

/**********************
 *      MACROS
 **********************/

/**********************
 *   GLOBAL FUNCTIONS
 **********************/

 /**
 * set a rect area
 * @param area_p point of rect area
 * @param x1 up left x
 * @param y1 up left y
 * @param x2 down right x
 * @param y2 down right y
 */
void wa_area_set(wa_area * area_p, int x1, int y1, int x2, int y2)
{
	area_p->x1 = x1;
	area_p->y1 = y1;
	area_p->x2 = x2;
	area_p->y2 = y2;
}
 
 
/**
 * set rect area width
 * @param area_p point of rect area
 * @param w rect area width
 */
void wa_area_set_width(wa_area * area_p, int w)
{
	area_p->x2 = area_p->x1 + w - 1;
}

/**
 * set rect area height
 * @param area_p point of rect area
 * @param w rect area height
 */
void wa_area_set_height(wa_area * area_p, int h)
{
	area_p->y2 = area_p->y1 + h - 1;
}

/**
 * get rect area width
 * @param area_p point of rect area
 * @return rect area width
 */
uint32_t wa_area_get_width(wa_area * area_p)
{
	return area_p->x2 - area_p->x1 + 1;
}

/**
 * get rect area height
 * @param area_p point of rect area
 * @return rect area height
 */
uint32_t wa_area_get_height(wa_area * area_p)
{
	return area_p->y2 - area_p->y1 + 1;
}
 
/**
 * set rect area start point
 * @param area_p point of rect area
 * @param x start point x
 * @param y start point y
 */
void wa_area_set_pos(wa_area * area_p, int x, int y)
{
	int w = wa_area_get_width(area_p);
	int h = wa_area_get_height(area_p);
	area_p->x1 = x;
	area_p->y1 = y;
	wa_area_set_width(area_p, w);
	wa_area_set_height(area_p, h);
}

/**
 * get size of rect area
 * @param area_p point of rect area
 * @return size of rect area
 */
uint32_t wa_area_get_size(wa_area * area_p)
{
	uint32_t size;

	size = (uint32_t)(area_p->x2 - area_p->x1 + 1) * 
									 (area_p->y2 - area_p->y1 + 1);

	return size;
}
 
 
 /**
 * get two rect area union
 * @param res_p area union
 * @param a1_p frist area
 * @param a2_p second area
 * @return wa_nok: no union with this two area  wa_ok:there is union with this two area
 */
wa_result wa_area_union(wa_area * res_p, wa_area * a1_p, wa_area * a2_p)
{
	wa_result union_ok = wa_ok;
	//get the smallest area
	res_p->x1 = WA_MATH_MAX(a1_p->x1, a2_p->x1);
	res_p->y1 = WA_MATH_MAX(a1_p->y1, a2_p->y1);
	res_p->x2 = WA_MATH_MIN(a1_p->x2, a2_p->x2);
	res_p->y2 = WA_MATH_MIN(a1_p->y2, a2_p->y2);

	//if x1,y1 bigger than x2,y2, that mean no union
	if((res_p->x1 > res_p->x2) ||
		 (res_p->y1 > res_p->y2))
	{
			union_ok = wa_nok;
	}

	return union_ok;
}
 
 
 /**
 * get the smallest rect include two rect area
 * @param res_p the smallest rect
 * @param a1_p frist area
 * @param a2_p second area
 */
void wa_area_join(wa_area * a_res_p, wa_area * a1_p, wa_area * a2_p)
{
	a_res_p->x1 = WA_MATH_MIN(a1_p->x1, a2_p->x1);
	a_res_p->y1 = WA_MATH_MIN(a1_p->y1, a2_p->y1);
	a_res_p->x2 = WA_MATH_MAX(a1_p->x2, a2_p->x2);
	a_res_p->y2 = WA_MATH_MAX(a1_p->y2, a2_p->y2);
}
 
 
 /**
 * check a point is on the area or not
 * @param a_p point of area
 * @param p_p point of point
 * @return wa_ok: point is on the area
 */
wa_result wa_area_is_point_on(wa_area * a_p, wa_point * p_p)
{
	wa_result is_on = wa_nok;

	if((p_p->x >= a_p->x1 && p_p->x <= a_p->x2) &&
		 ((p_p->y >= a_p->y1 && p_p->y <= a_p->y2)))
	{
			is_on = wa_ok;
	}

	return is_on;
}
 
 

/**
 * check two area connect or not
 * @param a1_p frist area
 * @param a2_p second area
 * @return wa_ok: two area connect
 */
wa_result wa_area_is_on(wa_area * a1_p,wa_area * a2_p)
{
	int x1,y1,x2,y2;
	x1 = WA_MATH_MAX(a1_p->x1, a2_p->x1);
	y1 = WA_MATH_MAX(a1_p->y1, a2_p->y1);
	x2 = WA_MATH_MIN(a1_p->x2, a2_p->x2);
	y2 = WA_MATH_MIN(a1_p->y2, a2_p->y2);

	if((x1>x2)||(y1>y2))
	{
		return wa_nok;
	}
	else
	{
		return wa_ok;
	}
	
}
 
/**
 * check asub_p is include by apar_p or not
 * @param asub_p include area
 * @param apar_p include by area
 * @return wa_ok:include all
 */
wa_result wa_area_is_in(wa_area * asub_p, wa_area * apar_p)
{
	wa_result is_in = wa_nok;

	if(asub_p->x1  >= apar_p->x1 &&
		 asub_p->y1  >= apar_p->y1 &&
		 asub_p->x2  <= apar_p->x2 &&
		 asub_p->y2  <= apar_p->y2)
	{
			is_in = wa_ok;
	}

	return is_in;
}
 
void wa_area_copy(wa_area* dst_area, wa_area* src_area)
{
	memcpy(dst_area,src_area,sizeof(wa_area));
}
 
/**********************
 *   STATIC FUNCTIONS
 **********************/
